package com.wonderland.butterfly.autoupdate.patch;

import com.wonderland.butterfly.util.FileUtil;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;

/**
 * 数据库增量自动提取工具
 */
public class DatabasePatch {
    //换行符
    private final String LINE_SEPARATOR = "\r\n";
    //增量文件数
    private static int fileNumber = 0;
    //数据库增量所在文件夹
    private String databasePatchDir;
    //补丁文件夹
    private String patchDir;

    public DatabasePatch(String databasePatchDir, String patchDir) {
        this.databasePatchDir = databasePatchDir;
        this.patchDir = patchDir;
    }

    /**
     * 第一个版本号大于第二个则返回true
     *
     * @param originalVersion 第一个版本号
     * @param targetVersion   第二个版本号
     * @return 第一个版本号大于第二个则返回true
     */
    private boolean isGreater(String originalVersion, String targetVersion) {
        try {
            String[] originalVersions = originalVersion.replace("v", "").split("\\.");
            String[] targetVersions = targetVersion.replace("v", "").split("\\.");
            for (int i = 0; i < Math.min(originalVersions.length, targetVersions.length); i++) {
                if (Double.parseDouble(originalVersions[i]) > Double.parseDouble(targetVersions[i])) {
                    return true;
                } else if (Double.parseDouble(originalVersions[i]) < Double.parseDouble(targetVersions[i])) {
                    return false;
                }
            }
        } catch (Exception e) {
        }
        return false;
    }

    /**
     * 第一个版本号大于等于第二个则返回true
     *
     * @param originalVersion 第一个版本号
     * @param targetVersion   第二个版本号
     * @return 第一个版本号大于等于第二个则返回true
     */
    private boolean isGreaterOrEqual(String originalVersion, String targetVersion) {
        if (isGreater(originalVersion, targetVersion)) {
            return true;
        } else if (originalVersion.equals(targetVersion)) {
            return true;
        }
        return false;
    }

    /**
     * 把文件按照文件名从小到大的排序，1.1<1.2<1.10
     *
     * @param targetArr 要排序的文件数组
     */
    public void fileSort(File[] targetArr) {
        File temp;
        for (int i = 0; i < targetArr.length; i++) {
            for (int j = i; j < targetArr.length; j++) {
                if (isGreater(targetArr[i].getName(), targetArr[j].getName())) {
                    temp = targetArr[i];
                    targetArr[i] = targetArr[j];
                    targetArr[j] = temp;
                }

            }
        }
    }

    /**
     * 递归获取某一文件夹下的所有sql文件，并拼接成一个string
     *
     * @param dir
     * @return
     */
    private String getAllSqlInDir(File dir) {
        File[] files = dir.listFiles();
        StringBuilder sb = new StringBuilder("");
        if (files != null) {
            for (File file : files) {
                if (file.isFile() && notContainSpecialFile(file.getName())) {
                    sb.append("-- ").append(file.getAbsoluteFile()).append(LINE_SEPARATOR)
                            .append(FileUtil.getTextFromText(file, LINE_SEPARATOR)).append(LINE_SEPARATOR);
                    fileNumber++;
                } else if (file.isDirectory()) {
                    sb.append(getAllSqlInDir(file)).append(LINE_SEPARATOR);
                }
            }
        }
        return sb.toString();
    }

    /**
     * 写txt
     *
     * @param filePath txt所在目录
     * @param content  内容
     */
    private void writeTxt(String filePath, String content) {
        try {
            FileWriter fw = new FileWriter(new File(filePath));
            fw.write(content);
            fw.close();
        } catch (FileNotFoundException ignored) {

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取数据库增量
     *
     * @param databasePatchDir 数据库增量文件夹
     * @param originalVersion  原版本
     * @param targetVersion    目标版本
     * @return 数据库增量string
     */
    public String getDatabasePatch(String databasePatchDir, String originalVersion, String targetVersion) {
        File databasePatch = new File(databasePatchDir);
        File[] databasePathVersion = databasePatch.listFiles();
        fileSort(databasePathVersion);
        StringBuilder sb = new StringBuilder("");
        if (databasePathVersion != null) {
            for (File mainVersion : databasePathVersion) {
                File[] files = mainVersion.listFiles();
                if (mainVersion.isDirectory() && notContainSpecialFile(mainVersion.getName()) && files != null) {
                    fileSort(files);
                    for (File file : files) {
                        if (notContainSpecialFile(file.getName()) && isGreater(file.getName(), originalVersion) && isGreaterOrEqual(targetVersion, file.getName())) {
                            sb.append(getAllSqlInDir(file)).append(LINE_SEPARATOR);
                        }
                    }
                }
            }
        }
        return sb.toString();
    }

    /**
     * 提取增量时忽略的文件夹
     *
     * @param fileName
     * @return
     */
    private boolean notContainSpecialFile(String fileName) {
        return !fileName.contains("DS_Store") && !fileName.contains("svn") && !fileName.contains("增量汇总");
    }

    public void generatePatch(String patchName, String originalVersion, String targetVersion) throws IOException {
        patchDir = patchDir + File.separator + patchName + File.separator;
        FileUtil.createDirectory(patchDir);
        writeTxt(patchDir + "sql.sql", getDatabasePatch(databasePatchDir, originalVersion, targetVersion));
        File file = new File(patchDir + targetVersion);
        file.createNewFile();
        System.out.println("文件数：" + fileNumber);
    }

}